# -*- coding: utf-8 -*-
"""
Module Description:角色状态逻辑处理工具
Date: 2015/9/7
Author:Bai Jin Ping
"""
from pyshare.const.enums.role import RoleStatus
from pyshare.framework.error_handle import GameException
from functools import wraps


def is_can_set_user_status(func):
    """检测是否可以设置"""
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        # 检测是否是注销状态
        if self.is_cancellation():
            raise GameException("角色已经注销，不能设置其它状态")
        return func(self, *args, **kwargs)
    return wrapper


class UserStatusUtils(object):
    """
    负责辅助角色状态相关的逻辑

    依据：
    算术基本定理：任何大于1的正整数n可以唯一表示成有限个素数的乘积: n=p_1p_2...p_s, 这里p_1≦p_2 ≦--≦p_s是素数
    自行推理：不相等的素数集合的集合元素之积一定不相等。

    !! UserStatus不能够是0.
    """

    INIT_USER_STATUS = RoleStatus.Normal

    def __init__(self, user_status=INIT_USER_STATUS):
        """
        :param user_status:当前角色状态
        """
        if user_status <= 0:
            user_status = self.get_init_status()

        self.user_status = user_status

    @staticmethod
    def get_init_status():
        """
        创建角色的初始状态
        """
        return UserStatusUtils.INIT_USER_STATUS

    def set_status(self, new_status):
        assert new_status > 0

        self.user_status = new_status

    def get_status(self):
        return self.user_status if self.user_status > 0 else self.get_init_status()

    def can_login(self):
        """
        角色是否允许登录
        """
        return True if (not self.is_freeze())and (not self.is_cancellation()) else False

    #####################
    #         聊天/邮件相关
    #####################
    def can_communicate(self):
        """
        角色是否允许聊天/发邮件
        """
        return True if self.user_status % RoleStatus.Gag != 0 else False

    @is_can_set_user_status
    def do_forbid_communicate(self):
        """
        设置角色不能聊天/发邮件
        """
        if self.can_communicate():
            self.user_status *= RoleStatus.Gag

    @is_can_set_user_status
    def undo_forbid_communicate(self):
        """
        恢复角色聊天/发邮件
        """
        if not self.can_communicate():
            self.user_status /= RoleStatus.Gag

    def by_shield_chat(self):
        """
        角色是否被屏蔽聊天
        """
        return True if self.user_status % RoleStatus.Shield == 0 else False

    @is_can_set_user_status
    def do_shield_chat(self):
        """
        设置角色被屏蔽聊天
        """
        if not self.by_shield_chat():
            self.user_status *= RoleStatus.Shield

    @is_can_set_user_status
    def undo_shield_chat(self):
        """
        恢复角色被屏蔽聊天
        """
        if self.by_shield_chat():
            self.user_status /= RoleStatus.Shield

    #####################
    #         登录相关
    #####################
    def is_freeze(self):
        """是否冻结"""
        return True if self.user_status % RoleStatus.Freeze == 0 else False

    @is_can_set_user_status
    def do_freeze(self):
        """
        设置角色冻结状态
        """
        if not self.is_freeze():
            self.user_status *= RoleStatus.Freeze

    @is_can_set_user_status
    def undo_freeze(self):
        """
        取消角色冻结状态
        """
        if self.is_freeze():
            self.user_status /= RoleStatus.Freeze

    #####################
    #         角色改名相关
    #####################
    def can_rename(self):
        """
        角色是否允许主动改名
        """
        return True if self.user_status % RoleStatus.BanRename != 0 else False

    @is_can_set_user_status
    def ban_rename(self):
        """
        禁止角色主动改名
        """
        if self.can_rename():
            self.user_status *= RoleStatus.BanRename

    @is_can_set_user_status
    def unban_rename(self):
        """
        准许角色主动改名
        """
        if not self.can_rename():
            self.user_status /= RoleStatus.BanRename

    #####################
    #         排行榜相关
    #####################
    def can_in_rank(self):
        """
        角色是否允许进入排行榜
        """
        return True if self.user_status % RoleStatus.OutRank != 0\
            and self.can_login() else False

    def do_revoke_from_rank(self):
        """
        设置角色不允许进入排行榜
        """
        if self.can_in_rank():
            self.user_status *= RoleStatus.OutRank

    @is_can_set_user_status
    def undo_revoke_from_rank(self):
        """
        恢复角色允许进入排行榜
        """
        if not self.can_in_rank():
            self.user_status /= RoleStatus.OutRank

    #####################
    #         注销相关
    #####################

    def is_cancellation(self):
        """是否已经注销"""
        return True if self.user_status % RoleStatus.Cancellation == 0 else False

    def do_cancellation(self):
        """设置角色注销状态"""
        if not self.is_cancellation():
            self.user_status = RoleStatus.Cancellation

    def undo_cancellation(self):
        """取消角色注销状态"""
        if self.is_cancellation():
            self.user_status /= RoleStatus.Cancellation

    def __str__(self):
        return 'UserStatus(%d)' % self.user_status


if __name__ == '__main__':
    def show_status(user_status_utils):
        print '#' * 30
        print user_status_utils
        print 'can_login', user_status_utils.can_login()
        print 'can_communicate', user_status_utils.can_communicate()
        print 'can_in_rank', user_status_utils.can_in_rank()
        print 'by_shield_chat', user_status_utils.by_shield_chat()
        print '#' * 30

    user_status_utils = UserStatusUtils(UserStatusUtils.get_init_status())
    print user_status_utils

    show_status(user_status_utils)

    user_status_utils.do_freeze()
    show_status(user_status_utils)

    user_status_utils.do_forbid_communicate()
    show_status(user_status_utils)

    user_status_utils.do_revoke_from_rank()
    show_status(user_status_utils)

    user_status_utils.do_shield_chat()
    show_status(user_status_utils)

    user_status_utils.undo_freeze()
    show_status(user_status_utils)

    user_status_utils.undo_forbid_communicate()
    show_status(user_status_utils)

    user_status_utils.undo_revoke_from_rank()
    show_status(user_status_utils)

    user_status_utils.undo_shield_chat()
    show_status(user_status_utils)

    print user_status_utils.get_status()

    user_status_utils.do_freeze()
    user_status_utils.undo_revoke_from_rank()
    print user_status_utils.get_status()

    print user_status_utils.do_forbid_communicate.__name__
    print user_status_utils.do_forbid_communicate.__doc__
